<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebCrawler 分析平台</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
    <style>
        :root {
            --primary-color: #3498db;
            --secondary-color: #2c3e50;
            --accent-color: #e74c3c;
            --light-bg: #f8f9fa;
            --dark-bg: #343a40;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f5f7f9;
        }

        .navbar {
            background-color: var(--secondary-color);
        }

        .card {
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            margin-bottom: 20px;
            transition: transform 0.2s;
        }

        .card:hover {
            transform: translateY(-5px);
        }

        .card-header {
            background-color: var(--primary-color);
            color: white;
            border-radius: 8px 8px 0 0 !important;
        }

        .btn-primary {
            background-color: var(--primary-color);
            border-color: var(--primary-color);
        }

        .btn-primary:hover {
            background-color: #2980b9;
            border-color: #2980b9;
        }

        .request-item {
            border-left: 4px solid var(--primary-color);
            padding: 10px 15px;
            margin-bottom: 10px;
            background-color: white;
            border-radius: 4px;
        }

        .request-get {
            border-left-color: #28a745;
        }

        .request-post {
            border-left-color: #ffc107;
        }

        .request-error {
            border-left-color: var(--accent-color);
        }

        .monitor-panel {
            height: 400px;
            overflow-y: auto;
            background-color: #2c3e50;
            color: #ecf0f1;
            padding: 15px;
            border-radius: 4px;
        }

        .monitor-item {
            padding: 8px 12px;
            margin-bottom: 8px;
            background-color: #34495e;
            border-radius: 4px;
            font-family: monospace;
        }

        .tab-pane {
            padding: 20px 0;
            display: none;
        }

        .tab-pane.active {
            display: block;
        }

        .stat-card {
            text-align: center;
            padding: 15px;
        }

        .stat-number {
            font-size: 2.5rem;
            font-weight: bold;
            color: var(--primary-color);
        }

        #responseBody {
            min-height: 200px;
            font-family: monospace;
            font-size: 0.9rem;
            white-space: pre-wrap;
        }

        .flow-step {
            background-color: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            padding: 15px;
            margin-bottom: 15px;
            position: relative;
        }

        .step-number {
            position: absolute;
            top: -10px;
            left: -10px;
            width: 30px;
            height: 30px;
            background-color: var(--primary-color);
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }

        .websocket-status {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin-right: 5px;
        }

        .status-connected {
            background-color: #28a745;
        }

        .status-disconnected {
            background-color: #dc3545;
        }

        .status-connecting {
            background-color: #ffc107;
        }

        .request-details pre {
            max-height: 200px;
            overflow-y: auto;
            white-space: pre-wrap;
        }

        .variable-extraction {
            background-color: #e8f4f8;
            border-radius: 4px;
            padding: 10px;
            margin-top: 10px;
        }

        .extraction-row {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
        }

        .extraction-row input {
            flex: 1;
        }

        .flow-variables-panel {
            background-color: #e8f4f8;
            border-radius: 4px;
            padding: 15px;
            margin-top: 15px;
        }

        .nav-link {
            cursor: pointer;
        }

        .edit-request-btn {
            margin-right: 5px;
        }

        .save-analysis-request-btn {
            margin-left: 5px;
        }

        .request-type-badge {
            font-size: 0.75rem;
            padding: 0.25em 0.4em;
            border-radius: 0.25rem;
            font-weight: 600;
        }

        .type-resource {
            background-color: #d1ecf1;
            color: #0c5460;
        }

        .type-navigation {
            background-color: #d4edda;
            color: #155724;
        }

        .type-data {
            background-color: #f8d7da;
            color: #721c24;
        }

        .type-extracted {
            background-color: #fff3cd;
            color: #856404;
        }

        .type-static {
            background-color: #e2e3e5;
            color: #383d41;
        }

        .type-dynamic {
            background-color: #cce5ff;
            color: #004085;
        }

        .filter-btn {
            margin-right: 5px;
            margin-bottom: 5px;
        }

        .filter-active {
            background-color: var(--primary-color);
            color: white;
        }

        /* 通知样式 */
        .notification {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 9999;
            min-width: 300px;
        }
    </style>
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark mb-4">
    <div class="container">
        <a class="navbar-brand" href="#">
            <i class="bi bi-diagram-3"></i> WebCrawler 分析平台
        </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav me-auto">
                <li class="nav-item">
                    <a class="nav-link active" data-tab="analysis">
                        <i class="bi bi-search"></i> 网站分析
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" data-tab="requests">
                        <i class="bi bi-list-check"></i> 请求管理
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" data-tab="flow">
                        <i class="bi bi-diagram-3"></i> 流程测试
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" data-tab="monitor">
                        <i class="bi bi-speedometer2"></i> 实时监控
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" data-tab="debug">
                        <i class="bi bi-bug"></i> 调试
                    </a>
                </li>
            </ul>
            <div class="d-flex">
                    <span class="navbar-text me-3">
                        <span class="websocket-status status-disconnected" id="wsStatus"></span>
                        <span id="wsStatusText">未连接</span>
                    </span>
                <button class="btn btn-outline-light btn-sm" id="settingsBtn">
                    <i class="bi bi-gear"></i>
                </button>
            </div>
        </div>
    </div>
</nav>

<div class="container">
    <!-- 网站分析标签页 -->
    <div class="tab-pane active" id="analysis">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">网站分析</h5>
                    </div>
                    <div class="card-body">
                        <form id="analysisForm">
                            <div class="row mb-3">
                                <div class="col-md-8">
                                    <label for="urlInput" class="form-label">目标网址</label>
                                    <input type="url" class="form-control" id="urlInput" placeholder="https://example.com" required>
                                </div>
                                <div class="col-md-4">
                                    <label class="form-label">&nbsp;</label>
                                    <button type="submit" class="btn btn-primary w-100">
                                        <i class="bi bi-search"></i> 开始分析
                                    </button>
                                    <button type="button" class="btn btn-warning" id="debugAnalysisBtn">
                                        <i class="bi bi-bug"></i> 调试分析
                                    </button>
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-md-6">
                                    <label for="usernameInput" class="form-label">用户名（可选）</label>
                                    <input type="text" class="form-control" id="usernameInput">
                                </div>
                                <div class="col-md-6">
                                    <label for="passwordInput" class="form-label">密码（可选）</label>
                                    <input type="password" class="form-control" id="passwordInput">
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>

        <div class="row mt-4">
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-number" id="totalRequests">0</div>
                    <div class="stat-label">总请求数</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-number" id="getRequests">0</div>
                    <div class="stat-label">GET请求</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-number" id="postRequests">0</div>
                    <div class="stat-label">POST请求</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-number" id="successRequests">0</div>
                    <div class="stat-label">成功请求</div>
                </div>
            </div>
        </div>

        <div class="row mt-4">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="mb-0">请求列表</h5>
                        <div>
                            <button class="btn btn-sm btn-outline-secondary" id="exportBtn">
                                <i class="bi bi-download"></i> 导出
                            </button>
                            <button class="btn btn-sm btn-outline-secondary" id="toggleDetailsBtn">
                                <i class="bi-list"></i> 切换详情
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label class="form-label">按类型筛选:</label>
                            <div id="typeFilters">
                                <button class="btn btn-sm btn-outline-primary filter-btn filter-active" data-type="all">全部</button>
                                <button class="btn btn-sm btn-outline-primary filter-btn" data-type="resource">资源</button>
                                <button class="btn btn-sm btn-outline-primary filter-btn" data-type="navigation">导航</button>
                                <button class="btn btn-sm btn-outline-primary filter-btn" data-type="data">数据</button>
                                <button class="btn btn-sm btn-outline-primary filter-btn" data-type="extracted">提取</button>
                                <button class="btn btn-sm btn-outline-primary filter-btn" data-type="Static">静态</button>
                                <button class="btn btn-sm btn-outline-primary filter-btn" data-type="Dynamic">动态</button>
                            </div>
                        </div>
                        <div id="requestsList">
                            <p class="text-center text-muted">暂无数据，请先分析网站</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 请求管理标签页 -->
    <div class="tab-pane" id="requests">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="mb-0">请求详情</h5>
                        <div>
                            <button class="btn btn-sm btn-success" id="saveRequestBtn">
                                <i class="bi bi-save"></i> 保存请求
                            </button>
                            <button class="btn btn-sm btn-primary" id="sendRequestBtn">
                                <i class="bi bi-send"></i> 发送请求
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <input type="hidden" id="editingRequestId">
                        <div class="row mb-3">
                            <div class="col-md-8">
                                <label for="reqUrl" class="form-label">URL</label>
                                <input type="url" class="form-control" id="reqUrl" placeholder="https://api.example.com/endpoint">
                            </div>
                            <div class="col-md-4">
                                <label for="reqMethod" class="form-label">方法</label>
                                <select class="form-select" id="reqMethod">
                                    <option value="GET">GET</option>
                                    <option value="POST">POST</option>
                                    <option value="PUT">PUT</option>
                                    <option value="DELETE">DELETE</option>
                                    <option value="PATCH">PATCH</option>
                                </select>
                            </div>
                        </div>

                        <div class="row mb-3">
                            <div class="col-md-12">
                                <label class="form-label">请求头</label>
                                <div id="requestHeaders">
                                    <div class="header-row row mb-2">
                                        <div class="col-md-5">
                                            <input type="text" class="form-control" placeholder="Header名称">
                                        </div>
                                        <div class="col-md-5">
                                            <input type="text" class="form-control" placeholder="Header值">
                                        </div>
                                        <div class="col-md-2">
                                            <button class="btn btn-sm btn-danger w-100 remove-header">
                                                <i class="bi bi-trash"></i>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                                <button class="btn btn-sm btn-outline-primary mt-2" id="addHeaderBtn">
                                    <i class="bi bi-plus"></i> 添加请求头
                                </button>
                            </div>
                        </div>

                        <div class="row mb-3">
                            <div class="col-md-12">
                                <label for="requestBody" class="form-label">请求体</label>
                                <textarea class="form-control" id="requestBody" rows="5" placeholder="{&#10;  &quot;key&quot;: &quot;value&quot;&#10;}"></textarea>
                            </div>
                        </div>

                        <div class="row">
                            <div class="col-md-12">
                                <div class="card">
                                    <div class="card-header">
                                        <h6 class="mb-0">响应</h6>
                                    </div>
                                    <div class="card-body">
                                        <div class="mb-2">
                                            <span class="badge bg-info" id="responseStatus">等待响应...</span>
                                            <span class="badge bg-secondary ms-2" id="responseTime">- ms</span>
                                        </div>
                                        <pre id="responseBody">暂无响应数据</pre>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="row mt-4">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="mb-0">已保存的请求</h5>
                        <button class="btn btn-sm btn-outline-secondary" id="refreshSavedBtn">
                            <i class="bi bi-arrow-clockwise"></i> 刷新
                        </button>
                    </div>
                    <div class="card-body">
                        <table class="table table-hover">
                            <thead>
                            <tr>
                                <th>方法</th>
                                <th>URL</th>
                                <th>状态</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody id="savedRequestsList">
                            <tr>
                                <td colspan="4" class="text-center text-muted">暂无保存的请求</td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 流程测试标签页 -->
    <div class="tab-pane" id="flow">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="mb-0">流程测试</h5>
                        <div>
                            <button class="btn btn-sm btn-success" id="saveFlowBtn">
                                <i class="bi bi-save"></i> 保存流程
                            </button>
                            <button class="btn btn-sm btn-primary" id="executeFlowBtn">
                                <i class="bi bi-play-circle"></i> 执行流程
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="row mb-3">
                            <div class="col-md-8">
                                <label for="flowName" class="form-label">流程名称</label>
                                <input type="text" class="form-control" id="flowName" placeholder="我的测试流程">
                            </div>
                        </div>

                        <div id="flowSteps">
                            <div class="flow-step">
                                <span class="step-number">1</span>
                                <h6>步骤 1</h6>
                                <div class="row mb-2">
                                    <div class="col-md-8">
                                        <label class="form-label">URL</label>
                                        <input type="url" class="form-control" placeholder="https://api.example.com/endpoint">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">方法</label>
                                        <select class="form-select">
                                            <option value="GET">GET</option>
                                            <option value="POST">POST</option>
                                            <option value="PUT">PUT</option>
                                            <option value="DELETE">DELETE</option>
                                        </select>
                                    </div>
                                </div>

                                <div class="row mb-2">
                                    <div class="col-md-12">
                                        <label class="form-label">请求体</label>
                                        <textarea class="form-control" rows="3" placeholder='{"key": "value"}'></textarea>
                                    </div>
                                </div>

                                <div class="variable-extraction">
                                    <h6>变量提取</h6>
                                    <div class="extraction-rows">
                                        <div class="extraction-row">
                                            <input type="text" class="form-control" placeholder="变量名">
                                            <input type="text" class="form-control" placeholder="JSON路径 (例: $.data.id)">
                                            <button class="btn btn-sm btn-danger remove-extraction">
                                                <i class="bi bi-trash"></i>
                                            </button>
                                        </div>
                                    </div>
                                    <button class="btn btn-sm btn-outline-primary mt-2 add-extraction">
                                        <i class="bi bi-plus"></i> 添加变量提取
                                    </button>
                                </div>

                                <button class="btn btn-sm btn-outline-danger remove-step">
                                    <i class="bi bi-trash"></i> 删除步骤
                                </button>
                            </div>
                        </div>

                        <button class="btn btn-sm btn-outline-primary mt-3" id="addStepBtn">
                            <i class="bi bi-plus-circle"></i> 添加步骤
                        </button>

                        <div class="flow-variables-panel">
                            <h6>流程变量说明</h6>
                            <p class="mb-1">您可以在后续步骤中使用已提取的变量:</p>
                            <ul class="mb-0">
                                <li>在URL或请求体中使用 <code>{{variableName}}</code> 引用变量</li>
                                <li>例如: <code>https://api.example.com/users/{{userId}}</code></li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="row mt-4">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="mb-0">已保存的流程</h5>
                        <button class="btn btn-sm btn-outline-secondary" id="refreshFlowsBtn">
                            <i class="bi bi-arrow-clockwise"></i> 刷新
                        </button>
                    </div>
                    <div class="card-body">
                        <table class="table table-hover">
                            <thead>
                            <tr>
                                <th>名称</th>
                                <th>步骤数</th>
                                <th>创建时间</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody id="savedFlowsList">
                            <tr>
                                <td colspan="4" class="text-center text-muted">暂无保存的流程</td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- 调试标签页 -->
    <div class="tab-pane" id="debug">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">调试功能</h5>
                    </div>
                    <div class="card-body">
                        <div class="row mb-3">
                            <div class="col-md-8">
                                <label for="debugPageId" class="form-label">页面ID</label>
                                <input type="text" class="form-control" id="debugPageId" placeholder="输入要调试的页面ID">
                            </div>
                            <div class="col-md-4">
                                <label class="form-label">&nbsp;</label>
                                <button class="btn btn-primary w-100" id="createDebugSessionBtn">
                                    <i class="bi bi-bug"></i> 创建调试会话
                                </button>
                            </div>
                        </div>

                        <div id="debugSessionControls" style="display: none;">
                            <div class="row mb-3">
                                <div class="col-md-12">
                                    <h6>断点设置</h6>
                                    <ul class="nav nav-tabs" id="breakpointTabs">
                                        <li class="nav-item">
                                            <a class="nav-link active" data-bs-toggle="tab" href="#jsBreakpointTab">JavaScript</a>
                                        </li>
                                        <li class="nav-item">
                                            <a class="nav-link" data-bs-toggle="tab" href="#requestBreakpointTab">请求</a>
                                        </li>
                                        <li class="nav-item">
                                            <a class="nav-link" data-bs-toggle="tab" href="#domBreakpointTab">DOM</a>
                                        </li>
                                        <li class="nav-item">
                                            <a class="nav-link" data-bs-toggle="tab" href="#exceptionBreakpointTab">异常</a>
                                        </li>
                                    </ul>
                                    <div class="tab-content mt-3">
                                        <div class="tab-pane fade show active" id="jsBreakpointTab">
                                            <div class="mb-2">
                                                <label for="jsBreakpointUrl" class="form-label">JavaScript断点URL</label>
                                                <input type="text" class="form-control" id="jsBreakpointUrl" placeholder="脚本URL">
                                            </div>
                                            <div class="row">
                                                <div class="col-md-6">
                                                    <label for="jsBreakpointLine" class="form-label">行号</label>
                                                    <input type="number" class="form-control" id="jsBreakpointLine" value="1" min="1">
                                                </div>
                                                <div class="col-md-6">
                                                    <label for="jsBreakpointColumn" class="form-label">列号</label>
                                                    <input type="number" class="form-control" id="jsBreakpointColumn" value="0" min="0">
                                                </div>
                                            </div>
                                            <div class="mb-2">
                                                <label for="jsBreakpointCondition" class="form-label">条件（可选）</label>
                                                <input type="text" class="form-control" id="jsBreakpointCondition" placeholder="条件表达式">
                                            </div>
                                            <button class="btn btn-sm btn-outline-primary" id="setJsBreakpointBtn">设置JavaScript断点</button>
                                        </div>

                                        <div class="tab-pane fade" id="requestBreakpointTab">
                                            <div class="mb-2">
                                                <label for="requestBreakpointPattern" class="form-label">请求断点模式</label>
                                                <input type="text" class="form-control" id="requestBreakpointPattern" placeholder="URL模式，如 *api*">
                                            </div>
                                            <button class="btn btn-sm btn-outline-primary mb-2" id="setRequestBreakpointBtn">设置请求断点</button>
                                        </div>

                                        <div class="tab-pane fade" id="domBreakpointTab">
                                            <div class="mb-2">
                                                <label for="domBreakpointNodeId" class="form-label">节点ID</label>
                                                <input type="number" class="form-control" id="domBreakpointNodeId" placeholder="DOM节点ID" min="1">
                                            </div>
                                            <div class="mb-2">
                                                <label for="domBreakpointType" class="form-label">断点类型</label>
                                                <select class="form-select" id="domBreakpointType">
                                                    <option value="subtree-modified">子树修改</option>
                                                    <option value="attribute-modified">属性修改</option>
                                                    <option value="node-removed">节点移除</option>
                                                </select>
                                            </div>
                                            <button class="btn btn-sm btn-outline-primary" id="setDomBreakpointBtn">设置DOM断点</button>
                                        </div>

                                        <div class="tab-pane fade" id="exceptionBreakpointTab">
                                            <div class="mb-2">
                                                <label for="exceptionBreakpointType" class="form-label">异常断点类型</label>
                                                <select class="form-select" id="exceptionBreakpointType">
                                                    <option value="all">所有异常</option>
                                                    <option value="uncaught">未捕获异常</option>
                                                    <option value="none">无</option>
                                                </select>
                                            </div>
                                            <button class="btn btn-sm btn-outline-primary" id="setExceptionBreakpointBtn">设置异常断点</button>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="row mb-3">
                                <div class="col-md-12">
                                    <h6>调试控制</h6>
                                    <div class="btn-group" role="group">
                                        <button class="btn btn-success" id="resumeDebugBtn">
                                            <i class="bi bi-play"></i> 继续执行
                                        </button>
                                        <button class="btn btn-warning" id="stepOverDebugBtn">
                                            <i class="bi bi-arrow-right"></i> 单步跳过
                                        </button>
                                        <button class="btn btn-warning" id="stepIntoDebugBtn">
                                            <i class="bi bi-arrow-down"></i> 单步进入
                                        </button>
                                        <button class="btn btn-warning" id="stepOutDebugBtn">
                                            <i class="bi bi-arrow-up"></i> 单步跳出
                                        </button>
                                        <button class="btn btn-danger" id="stopDebugBtn">
                                            <i class="bi bi-stop"></i> 停止调试
                                        </button>
                                    </div>
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-md-12">
                                    <h6>变量信息</h6>
                                    <div class="card">
                                        <div class="card-body">
                                            <div class="d-flex justify-content-between align-items-center mb-2">
                                                <h6 class="mb-0">当前变量</h6>
                                                <button class="btn btn-sm btn-outline-primary" id="refreshVariablesBtn">
                                                    <i class="bi bi-arrow-repeat"></i> 刷新
                                                </button>
                                            </div>
                                            <pre id="debugVariables" class="mb-0" style="max-height: 300px; overflow-y: auto;">暂无变量信息</pre>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="row mt-3">
                                <div class="col-md-12">
                                    <h6>已设置的断点</h6>
                                    <div class="card">
                                        <div class="card-body">
                                            <table class="table table-sm table-hover">
                                                <thead>
                                                <tr>
                                                    <th>类型</th>
                                                    <th>目标</th>
                                                    <th>位置</th>
                                                    <th>操作</th>
                                                </tr>
                                                </thead>
                                                <tbody id="breakpointsList">
                                                <tr>
                                                    <td colspan="4" class="text-center text-muted">暂无断点</td>
                                                </tr>
                                                </tbody>
                                            </table>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div id="debugStatus" class="mt-3">
                            <div class="alert alert-info mb-0">请输入页面ID并创建调试会话</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 实时监控标签页 -->
    <div class="tab-pane" id="monitor">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="mb-0">实时请求监控</h5>
                        <div>
                            <button class="btn btn-sm btn-success" id="startMonitorBtn">
                                <i class="bi bi-record-circle"></i> 开始监控
                            </button>
                            <button class="btn btn-sm btn-danger" id="stopMonitorBtn" disabled>
                                <i class="bi bi-stop-circle"></i> 停止监控
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="row mb-3">
                            <div class="col-md-12">
                                <label for="monitorUrl" class="form-label">监控目标URL</label>
                                <input type="url" class="form-control" id="monitorUrl" placeholder="https://example.com">
                            </div>
                        </div>

                        <div class="row mb-3">
                            <div class="col-md-12">
                                <div class="form-check form-switch">
                                    <input class="form-check-input" type="checkbox" id="interceptToggle">
                                    <label class="form-check-label" for="interceptToggle">启用请求拦截</label>
                                </div>
                            </div>
                        </div>

                        <div class="row mb-3" id="interceptPatternSection" style="display: none;">
                            <div class="col-md-12">
                                <label for="interceptPattern" class="form-label">拦截模式（支持通配符 * 和 ?）</label>
                                <input type="text" class="form-control" id="interceptPattern" placeholder="*/api/*">
                                <div class="form-text">例如：*/api/* 会拦截所有包含 /api/ 的URL</div>
                            </div>
                        </div>

                        <!-- HTTPS流量解密设置 -->
                        <div class="row mb-3">
                            <div class="col-md-12">
                                <div class="card bg-light">
                                    <div class="card-body">
                                        <h6 class="card-title">HTTPS流量解密</h6>
                                        <p class="card-text">
                                            为了能够解密HTTPS流量，您需要安装我们的CA证书到您的系统或浏览器信任存储区。
                                        </p>
                                        <button class="btn btn-sm btn-primary" id="downloadCertBtn">
                                            <i class="bi bi-download"></i> 下载CA证书
                                        </button>
                                        <button class="btn btn-sm btn-outline-secondary" id="checkCertBtn">
                                            <i class="bi bi-check-circle"></i> 检查证书状态
                                        </button>
                                        <div id="certStatus" class="mt-2"></div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="monitor-panel" id="monitorPanel">
                            <div class="text-center text-muted">监控未启动</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<footer class="mt-5 py-3 bg-light">
    <div class="container text-center">
        <span class="text-muted">WebCrawler 分析平台 &copy; 2023</span>
    </div>
</footer>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
    // 全局变量
    let ws = null;
    let isConnected = false;
    let currentRequests = []; // 保存当前显示的请求
    let notificationContainer = null;
    let currentDebugSessionId = null;

    // 页面初始化
    document.addEventListener('DOMContentLoaded', function() {
        // 创建通知容器
        notificationContainer = document.createElement('div');
        notificationContainer.id = 'notificationContainer';
        document.body.appendChild(notificationContainer);

        // 连接WebSocket
        connectWebSocket();

        // 标签页切换功能
        const tabLinks = document.querySelectorAll('.nav-link[data-tab]');
        tabLinks.forEach(link => {
            link.addEventListener('click', function(e) {
                e.preventDefault();

                // 移除所有活动状态
                document.querySelectorAll('.nav-link').forEach(navLink => {
                    navLink.classList.remove('active');
                });
                document.querySelectorAll('.tab-pane').forEach(tabPane => {
                    tabPane.classList.remove('active');
                });

                // 添加当前活动状态
                this.classList.add('active');
                const tabId = this.getAttribute('data-tab');
                document.getElementById(tabId).classList.add('active');
            });
        });

        // 添加类型筛选按钮事件监听器
        const filterButtons = document.querySelectorAll('.filter-btn');
        filterButtons.forEach(button => {
            button.addEventListener('click', function() {
                // 更新活动状态
                filterButtons.forEach(btn => btn.classList.remove('filter-active'));
                this.classList.add('filter-active');

                // 获取筛选类型
                const filterType = this.getAttribute('data-type');

                // 应用筛选
                filterRequests(filterType);
            });
        });

        // 通用事件监听器设置
        setupEventListeners();

        // 初始化数据
        refreshSavedRequests();
        refreshSavedFlows();

        // 初始化调试控制状态
        disableDebugControls();
    });

    // 统一设置事件监听器
    function setupEventListeners() {
        // 表单提交事件
        const forms = {
            'analysisForm': analyzeWebsite,
            // 可以添加更多表单处理
        };

        Object.keys(forms).forEach(formId => {
            const form = document.getElementById(formId);
            if (form) {
                form.addEventListener('submit', function(e) {
                    e.preventDefault();
                    forms[formId]();
                });
            }
        });

        // 按钮点击事件
        const buttons = {
            'interceptToggle': toggleInterceptPattern,
            'downloadCertBtn': downloadCACertificate,
            'checkCertBtn': checkCertificateStatus,
            'addHeaderBtn': addHeaderRow,
            'sendRequestBtn': sendRequest,
            'saveRequestBtn': handleSaveRequest,
            'refreshSavedBtn': refreshSavedRequests,
            'addStepBtn': addFlowStep,
            'executeFlowBtn': executeFlow,
            'saveFlowBtn': saveFlow,
            'refreshFlowsBtn': refreshSavedFlows,
            'startMonitorBtn': startMonitoring,
            'stopMonitorBtn': stopMonitoring,
            'createDebugSessionBtn': createDebugSessionHandler,
            'setJsBreakpointBtn': setJsBreakpointHandler,
            'setRequestBreakpointBtn': setRequestBreakpointHandler,
            'setDomBreakpointBtn': setDomBreakpointHandler,
            'setExceptionBreakpointBtn': setExceptionBreakpointHandler,
            'resumeDebugBtn': resumeDebugHandler,
            'stepOverDebugBtn': stepOverDebugHandler,
            'stepIntoDebugBtn': stepIntoDebugHandler,
            'stepOutDebugBtn': stepOutDebugHandler,
            'stopDebugBtn': stopDebugHandler,
            'refreshVariablesBtn': refreshVariablesHandler,
            'debugAnalysisBtn': debugAnalysisHandler
        };

        Object.keys(buttons).forEach(buttonId => {
            const button = document.getElementById(buttonId);
            if (button) {
                button.addEventListener('click', function(e) {
                    e.preventDefault();
                    buttons[buttonId]();
                });
            }
        });
    }

    // 处理拦截模式切换
    function toggleInterceptPattern() {
        const interceptPatternSection = document.getElementById('interceptPatternSection');
        const interceptToggle = document.getElementById('interceptToggle');
        if (interceptPatternSection) {
            interceptPatternSection.style.display = interceptToggle.checked ? 'block' : 'none';
        }
    }

    // 处理保存请求按钮点击
    function handleSaveRequest() {
        const editingRequestId = document.getElementById('editingRequestId').value;
        if (editingRequestId) {
            updateRequest(editingRequestId);
        } else {
            saveRequest();
        }
    }

    // 委托事件处理
    document.addEventListener('click', function(e) {
        // 处理各种按钮点击事件
        handleButtonClick(e);
    });

    // 统一处理按钮点击事件
    function handleButtonClick(e) {
        // 定义按钮处理映射
        const buttonHandlers = {
            'remove-header': handleRemoveHeader,
            'remove-step': handleRemoveStep,
            'view-details': handleViewDetails,
            'load-request': handleLoadRequest,
            'edit-request': handleEditRequest,
            'delete-request': handleDeleteRequest,
            'save-analysis-request': handleSaveAnalysisRequest,
            'load-flow': handleLoadFlow,
            'delete-flow': handleDeleteFlow,
            'add-extraction': handleAddExtraction,
            'remove-extraction': handleRemoveExtraction
        };

        // 遍历处理映射，找到对应的处理器
        for (const className in buttonHandlers) {
            if (e.target.classList.contains(className) ||
                (e.target.parentElement && e.target.parentElement.classList.contains(className))) {
                e.preventDefault();
                buttonHandlers[className](e);
                return;
            }
        }
    }

    // 处理删除请求头
    function handleRemoveHeader(e) {
        const button = e.target.classList.contains('remove-header') ?
            e.target : e.target.parentElement;
        if (button.closest('.header-row')) {
            button.closest('.header-row').remove();
        }
    }

    // 处理删除步骤
    function handleRemoveStep(e) {
        const button = e.target.classList.contains('remove-step') ?
            e.target : e.target.parentElement;
        const flowStep = button.closest('.flow-step');
        if (flowStep) {
            flowStep.remove();
            renumberFlowSteps();
        }
    }

    // 处理查看详情
    function handleViewDetails(e) {
        const button = e.target.classList.contains('view-details') ?
            e.target : e.target.parentElement;
        const details = button.closest('.request-item').querySelector('.request-details');
        if (details) {
            details.style.display = details.style.display === 'none' ? 'block' : 'none';
        }
    }

    // 处理加载请求
    function handleLoadRequest(e) {
        const button = e.target.classList.contains('load-request') ?
            e.target : e.target.parentElement;
        const requestData = button.getAttribute('data-request');
        if (requestData) {
            const request = safeJsonParse(requestData);
            if (request) {
                loadRequestIntoEditor(request);
                // 清除编辑状态
                document.getElementById('editingRequestId').value = '';
                document.getElementById('saveRequestBtn').innerHTML = '<i class="bi bi-save"></i> 保存请求';
            }
        }
    }

    // 处理编辑请求
    function handleEditRequest(e) {
        const button = e.target.classList.contains('edit-request') ?
            e.target : e.target.parentElement;
        const requestData = button.getAttribute('data-request');
        if (requestData) {
            const request = safeJsonParse(requestData);
            if (request) {
                loadRequestIntoEditor(request);
                // 设置编辑状态
                document.getElementById('editingRequestId').value = request.requestId;
                document.getElementById('saveRequestBtn').innerHTML = '<i class="bi bi-save"></i> 更新请求';
            }
        }
    }

    // 处理删除请求
    function handleDeleteRequest(e) {
        const button = e.target.classList.contains('delete-request') ?
            e.target : e.target.parentElement;
        const requestId = button.getAttribute('data-id');
        if (requestId) {
            deleteRequest(requestId);
        }
    }

    // 处理保存分析请求
    function handleSaveAnalysisRequest(e) {
        const button = e.target.classList.contains('save-analysis-request') ?
            e.target : e.target.parentElement;
        const requestData = button.getAttribute('data-request');
        if (requestData) {
            const request = safeJsonParse(requestData);
            if (request) {
                saveAnalysisRequest(request);
            }
        }
    }

    // 处理加载流程
    function handleLoadFlow(e) {
        const button = e.target.classList.contains('load-flow') ?
            e.target : e.target.parentElement;
        const flowData = button.getAttribute('data-flow');
        if (flowData) {
            const flow = safeJsonParse(flowData);
            if (flow) {
                loadFlowIntoEditor(flow);
            }
        }
    }

    // 处理删除流程
    function handleDeleteFlow(e) {
        const button = e.target.classList.contains('delete-flow') ?
            e.target : e.target.parentElement;
        const flowId = button.getAttribute('data-id');
        if (flowId) {
            deleteFlow(flowId);
        }
    }

    // 处理添加提取变量
    function handleAddExtraction(e) {
        const button = e.target.classList.contains('add-extraction') ?
            e.target : e.target.parentElement;
        const extractionRows = button.closest('.variable-extraction').querySelector('.extraction-rows');
        if (extractionRows) {
            addExtractionRow(extractionRows);
        }
    }

    // 处理删除提取变量
    function handleRemoveExtraction(e) {
        const button = e.target.classList.contains('remove-extraction') ?
            e.target : e.target.parentElement;
        const extractionRow = button.closest('.extraction-row');
        if (extractionRow &&
            extractionRow.parentElement.querySelectorAll('.extraction-row').length > 1) {
            extractionRow.remove();
        } else {
            showNotification('至少需要保留一个变量提取项', 'warning');
        }
    }

    // 安全解析JSON
    function safeJsonParse(jsonString) {
        try {
            return JSON.parse(jsonString);
        } catch (e) {
            console.error('JSON解析错误:', e);
            showNotification('数据解析失败', 'danger');
            return null;
        }
    }

    // 安全字符串化JSON并转义单引号
    function safeJsonStringifyAndEscape(obj) {
        try {
            return JSON.stringify(obj).replace(/'/g, "&#39;");
        } catch (e) {
            console.error('JSON序列化错误:', e);
            return '';
        }
    }

    // 统一的请求发送函数
    function sendApiRequest(url, options) {
        return fetch(url, options)
            .then(response => response.json())
            .catch(error => {
                console.error('请求失败:', error);
                showNotification('请求失败: ' + error.message, 'danger');
                throw error;
            });
    }

    // WebSocket连接管理
    function connectWebSocket() {
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const wsUrl = `${protocol}//${window.location.host}/ws/monitor`;

        try {
            ws = new WebSocket(wsUrl);
            updateWebSocketStatus('connecting', '连接中...');

            ws.onopen = function() {
                isConnected = true;
                updateWebSocketStatus('connected', '已连接');
                console.log('WebSocket连接已建立');
            };

            ws.onmessage = function(event) {
                handleWebSocketMessage(event.data);
            };

            ws.onclose = function() {
                isConnected = false;
                updateWebSocketStatus('disconnected', '连接已断开');
                console.log('WebSocket连接已关闭');

                // 尝试重新连接
                setTimeout(connectWebSocket, 5000);
            };

            ws.onerror = function(error) {
                console.error('WebSocket错误:', error);
                updateWebSocketStatus('disconnected', '连接错误');
            };
        } catch (error) {
            console.error('无法建立WebSocket连接:', error);
            updateWebSocketStatus('disconnected', '连接失败');
        }
    }

    function updateWebSocketStatus(status, text) {
        const statusElem = document.getElementById('wsStatus');
        const textElem = document.getElementById('wsStatusText');

        statusElem.className = 'websocket-status';
        if (status === 'connected') {
            statusElem.classList.add('status-connected');
        } else if (status === 'connecting') {
            statusElem.classList.add('status-connecting');
        } else {
            statusElem.classList.add('status-disconnected');
        }

        textElem.textContent = text;
    }

    function handleWebSocketMessage(data) {
        try {
            const message = JSON.parse(data);
            if (message.type === 'request') {
                addMonitorRequest(message.request);
            }
        } catch (e) {
            console.error('解析WebSocket消息失败:', e);
        }
    }

    function addMonitorRequest(request) {
        const panel = document.getElementById('monitorPanel');
        if (panel.firstChild?.textContent === '监控未启动') {
            panel.innerHTML = '';
        }

        const methodColor = request.method === 'GET' ? 'success' :
            request.method === 'POST' ? 'warning' : 'info';

        const item = document.createElement('div');
        item.className = 'monitor-item';
        item.innerHTML = `
                <span class="badge bg-${methodColor}">${escapeHtml(request.method)}</span>
                <span>${escapeHtml(request.url)}</span>
                ${request.status ? `<span class="badge bg-${request.status >= 400 ? 'danger' : 'success'} float-end">${request.status}</span>` : ''}
            `;

        panel.appendChild(item);
        panel.scrollTop = panel.scrollHeight;
    }

    // 网站分析功能
    function analyzeWebsite() {
        const urlInput = document.getElementById('urlInput');
        const usernameInput = document.getElementById('usernameInput');
        const passwordInput = document.getElementById('passwordInput');

        if (!urlInput || !urlInput.value) {
            showNotification('请输入URL', 'warning');
            return;
        }

        // URL格式验证
        try {
            new URL(urlInput.value);
        } catch (e) {
            showNotification('请输入有效的URL', 'warning');
            return;
        }

        const url = urlInput.value;
        const username = usernameInput ? usernameInput.value : '';
        const password = passwordInput ? passwordInput.value : '';

        // 显示加载状态
        const requestsList = document.getElementById('requestsList');
        if (requestsList) {
            requestsList.innerHTML = `
                <div class="text-center">
                    <div class="spinner-border text-primary" role="status">
                        <span class="visually-hidden">加载中...</span>
                    </div>
                    <p class="mt-2">正在分析网站，请稍候...</p>
                </div>
            `;
        }

        // 发送分析请求
        fetch('/api/analyze', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({
                'url': url,
                'username': username,
                'password': password
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 更新统计信息
                    updateStats(data.requests);
                    // 更新请求列表
                    displayRequests(data.requests);
                } else {
                    if (requestsList) {
                        requestsList.innerHTML = `<div class="alert alert-danger">分析失败: ${escapeHtml(data.error)}</div>`;
                    }
                }
            })
            .catch(error => {
                console.error('分析请求失败:', error);
                if (requestsList) {
                    requestsList.innerHTML = `<div class="alert alert-danger">请求失败: ${escapeHtml(error.message)}</div>`;
                }
            });
    }

    function updateStats(requests) {
        const totalRequests = requests.length;
        const getRequests = requests.filter(r => r.method === 'GET').length;
        const postRequests = requests.filter(r => r.method === 'POST').length;
        const successRequests = requests.filter(r => r.status >= 200 && r.status < 300).length;

        document.getElementById('totalRequests').textContent = totalRequests;
        document.getElementById('getRequests').textContent = getRequests;
        document.getElementById('postRequests').textContent = postRequests;
        document.getElementById('successRequests').textContent = successRequests;
    }

    function displayRequests(requests) {
        const requestsList = document.getElementById('requestsList');
        if (!requestsList) return;

        // 保存当前请求以便后续筛选
        currentRequests = requests;

        if (!requests || requests.length === 0) {
            requestsList.innerHTML = '<div class="text-center text-muted">未找到请求</div>';
            return;
        }

        // 显示所有请求（默认）
        renderRequests(requests);
    }

    function renderRequests(requests) {
        const requestsList = document.getElementById('requestsList');
        if (!requestsList) return;

        let html = '';
        requests.forEach((request, index) => {
            const methodClass = request.method === 'GET' ? 'request-get' :
                request.method === 'POST' ? 'request-post' : 'request-other';

            // 获取类型显示文本和CSS类
            let typeText = '未知';
            let typeClass = '';

            if (request.type) {
                switch (request.type.toLowerCase()) {
                    case 'resource':
                        typeText = '资源';
                        typeClass = 'type-resource';
                        break;
                    case 'navigation':
                        typeText = '导航';
                        typeClass = 'type-navigation';
                        break;
                    case 'data':
                        typeText = '数据';
                        typeClass = 'type-data';
                        break;
                    case 'extracted':
                        typeText = '提取';
                        typeClass = 'type-extracted';
                        break;
                    default:
                        typeText = request.type;
                        typeClass = 'type-extracted';
                }
            }

            // 如果没有type但有source，则根据source判断
            if (!request.type && request.source) {
                if (request.source.includes('Static')) {
                    typeText = '静态';
                    typeClass = 'type-static';
                } else if (request.source.includes('Dynamic')) {
                    typeText = '动态';
                    typeClass = 'type-dynamic';
                } else {
                    typeText = request.source;
                    typeClass = 'type-static';
                }
            }

            html += `
                <div class="request-item ${methodClass}" data-type="${request.type || (request.source ? (request.source.includes('Static') ? 'Static' : (request.source.includes('Dynamic') ? 'Dynamic' : request.source)) : 'unknown')}">
                    <div class="d-flex justify-content-between align-items-center">
                        <div>
                            <span class="badge bg-primary">${escapeHtml(request.method)}</span>
                            <span class="badge ${typeClass} request-type-badge ms-2">${escapeHtml(typeText)}</span>
                            <span class="ms-2">${escapeHtml(request.url)}</span>
                        </div>
                        <div>
                            <button class="btn btn-sm btn-outline-primary view-details">
                                <i class="bi bi-eye"></i> 详情
                            </button>
                            <button class="btn btn-sm btn-outline-success load-request"
                                    data-request='${safeJsonStringifyAndEscape(request)}'>
                                <i class="bi bi-arrow-repeat"></i> 加载
                            </button>
                            <button class="btn btn-sm btn-outline-info save-analysis-request save-analysis-request-btn"
                                    data-request='${safeJsonStringifyAndEscape(request)}'>
                                <i class="bi bi-save"></i> 保存
                            </button>
                        </div>
                    </div>
                    <div class="request-details mt-2" style="display: none;">
                        <div class="card">
                            <div class="card-body">
                                <h6>请求头</h6>
                                <pre>${JSON.stringify(request.requestHeaders || {}, null, 2)}</pre>
                                ${request.requestBody ? `
                                    <h6>请求体</h6>
                                    <pre>${escapeHtml(request.requestBody)}</pre>
                                ` : ''}
                                ${request.responseBody ? `
                                    <h6>响应体</h6>
                                    <pre>${escapeHtml(request.responseBody)}</pre>
                                ` : ''}
                                ${request.source ? `<p><strong>来源:</strong> ${escapeHtml(request.source)}</p>` : ''}
                                ${request.type ? `<p><strong>类型:</strong> ${escapeHtml(request.type)}</p>` : ''}
                            </div>
                        </div>
                    </div>
                </div>
            `;
        });

        requestsList.innerHTML = html;
    }

    function filterRequests(filterType) {
        if (filterType === 'all') {
            renderRequests(currentRequests);
            return;
        }

        let filteredRequests;
        if (filterType === 'Static' || filterType === 'Dynamic') {
            // 按source筛选
            filteredRequests = currentRequests.filter(request =>
                request.source && request.source.includes(filterType)
            );
        } else {
            // 按type筛选
            filteredRequests = currentRequests.filter(request =>
                request.type && request.type.toLowerCase() === filterType.toLowerCase()
            );

            // 如果按type筛选没有结果，尝试按source筛选
            if (filteredRequests.length === 0) {
                filteredRequests = currentRequests.filter(request =>
                    request.source && request.source.toLowerCase().includes(filterType.toLowerCase())
                );
            }
        }

        renderRequests(filteredRequests);
    }

    // 请求管理功能
    function addHeaderRow(name = '', value = '') {
        const container = document.getElementById('requestHeaders');
        if (!container) return;

        const row = document.createElement('div');
        row.className = 'header-row row mb-2';
        row.innerHTML = `
            <div class="col-md-5">
                <input type="text" class="form-control" placeholder="Header名称" value="${escapeHtml(name)}">
            </div>
            <div class="col-md-5">
                <input type="text" class="form-control" placeholder="Header值" value="${escapeHtml(value)}">
            </div>
            <div class="col-md-2">
                <button class="btn btn-sm btn-danger w-100 remove-header">
                    <i class="bi bi-trash"></i>
                </button>
            </div>
        `;
        container.appendChild(row);
    }

    function sendRequest() {
        const reqUrl = document.getElementById('reqUrl');
        const reqMethod = document.getElementById('reqMethod');
        const requestBody = document.getElementById('requestBody');

        if (!reqUrl || !reqMethod) {
            showNotification('缺少必要的请求参数', 'warning');
            return;
        }

        // URL格式验证
        try {
            new URL(reqUrl.value);
        } catch (e) {
            showNotification('请输入有效的URL', 'warning');
            return;
        }

        const url = reqUrl.value;
        const method = reqMethod.value;
        const body = requestBody ? requestBody.value : '';

        // 收集请求头
        const headers = {};
        const headerRows = document.querySelectorAll('.header-row');
        headerRows.forEach(row => {
            const nameInput = row.querySelector('input:first-child');
            const valueInput = row.querySelector('input:last-child');
            if (nameInput && valueInput && nameInput.value && valueInput.value) {
                headers[nameInput.value] = valueInput.value;
            }
        });

        // 显示加载状态
        const responseStatus = document.getElementById('responseStatus');
        const responseBody = document.getElementById('responseBody');
        const responseTime = document.getElementById('responseTime');

        if (responseStatus) {
            responseStatus.className = 'badge bg-info';
            responseStatus.textContent = '请求中...';
        }

        if (responseBody) {
            responseBody.textContent = '请求中...';
        }

        if (responseTime) {
            responseTime.textContent = '- ms';
        }

        const startTime = Date.now();

        // 发送请求
        fetch('/api/requests/send', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                ...headers
            },
            body: JSON.stringify({
                url: url,
                method: method,
                requestBody: method !== 'GET' ? body : undefined,
                requestHeaders: headers
            })
        })
            .then(response => response.json())
            .then(data => {
                const endTime = Date.now();
                const duration = endTime - startTime;

                if (data.success && data.data) {
                    if (responseStatus) {
                        responseStatus.className = 'badge bg-success';
                        responseStatus.textContent = `状态: ${data.data.status}`;
                    }

                    if (responseTime) {
                        responseTime.textContent = `${duration} ms`;
                    }

                    try {
                        // 尝试格式化JSON响应
                        if (responseBody) {
                            const formatted = JSON.stringify(JSON.parse(data.data.responseBody), null, 2);
                            responseBody.textContent = formatted;
                        }
                    } catch {
                        if (responseBody) {
                            responseBody.textContent = data.data.responseBody;
                        }
                    }
                } else {
                    if (responseStatus) {
                        responseStatus.className = 'badge bg-danger';
                        responseStatus.textContent = '错误';
                    }
                    if (responseBody) {
                        responseBody.textContent = data.message || '未知错误';
                    }
                }
            })
            .catch(error => {
                console.error('发送请求时出错:', error);
                if (responseStatus) {
                    responseStatus.className = 'badge bg-danger';
                    responseStatus.textContent = '错误';
                }
                if (responseBody) {
                    responseBody.textContent = '请求失败: ' + error.message;
                }
            });
    }

    function saveRequest() {
        // 检查是否处于编辑状态
        const editingRequestId = document.getElementById('editingRequestId').value;
        if (editingRequestId) {
            // 如果存在editingRequestId，则执行更新操作
            updateRequest(editingRequestId);
            return;
        }

        const reqUrl = document.getElementById('reqUrl');
        const reqMethod = document.getElementById('reqMethod');
        const requestBody = document.getElementById('requestBody');

        if (!reqUrl || !reqMethod) {
            showNotification('缺少必要的请求参数', 'warning');
            return;
        }

        // URL格式验证
        try {
            new URL(reqUrl.value);
        } catch (e) {
            showNotification('请输入有效的URL', 'warning');
            return;
        }

        const url = reqUrl.value;
        const method = reqMethod.value;
        const body = requestBody ? requestBody.value : '';

        // 收集请求头
        const headers = {};
        const headerRows = document.querySelectorAll('.header-row');
        headerRows.forEach(row => {
            const nameInput = row.querySelector('input:first-child');
            const valueInput = row.querySelector('input:last-child');
            if (nameInput && valueInput && nameInput.value && valueInput.value) {
                headers[nameInput.value] = valueInput.value;
            }
        });

        const request = {
            url: url,
            method: method,
            requestBody: body,
            requestHeaders: headers
        };

        // 发送保存请求
        fetch('/api/requests/save', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(request)
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('请求已保存', 'success');
                    refreshSavedRequests();
                } else {
                    showNotification('保存失败: ' + (data.message || '未知错误'), 'danger');
                }
            })
            .catch(error => {
                console.error('保存请求时出错:', error);
                showNotification('保存失败: ' + error.message, 'danger');
            });
    }

    function saveAnalysisRequest(request) {
        // 发送保存请求
        fetch('/api/requests/save', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(request)
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('请求已保存', 'success');
                    refreshSavedRequests();
                } else {
                    showNotification('保存失败: ' + (data.message || '未知错误'), 'danger');
                }
            })
            .catch(error => {
                console.error('保存请求时出错:', error);
                showNotification('保存失败: ' + error.message, 'danger');
            });
    }

    function updateRequest(requestId) {
        const reqUrl = document.getElementById('reqUrl');
        const reqMethod = document.getElementById('reqMethod');
        const requestBody = document.getElementById('requestBody');

        if (!reqUrl || !reqMethod) {
            showNotification('缺少必要的请求参数', 'warning');
            return;
        }

        // URL格式验证
        try {
            new URL(reqUrl.value);
        } catch (e) {
            showNotification('请输入有效的URL', 'warning');
            return;
        }

        const url = reqUrl.value;
        const method = reqMethod.value;
        const body = requestBody ? requestBody.value : '';

        // 收集请求头
        const headers = {};
        const headerRows = document.querySelectorAll('.header-row');
        headerRows.forEach(row => {
            const nameInput = row.querySelector('input:first-child');
            const valueInput = row.querySelector('input:last-child');
            if (nameInput && valueInput && nameInput.value && valueInput.value) {
                headers[nameInput.value] = valueInput.value;
            }
        });

        const request = {
            url: url,
            method: method,
            requestBody: body,
            requestHeaders: headers
        };

        // 发送更新请求
        fetch(`/api/requests/update/${requestId}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(request)
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('请求已更新', 'success');
                    refreshSavedRequests();

                    // 重置编辑状态
                    document.getElementById('editingRequestId').value = '';
                    const saveBtn = document.getElementById('saveRequestBtn');
                    if (saveBtn) {
                        saveBtn.innerHTML = '<i class="bi bi-save"></i> 保存请求';
                    }
                } else {
                    showNotification('更新失败: ' + (data.message || '未知错误'), 'danger');
                }
            })
            .catch(error => {
                console.error('更新请求时出错:', error);
                showNotification('更新失败: ' + error.message, 'danger');
            });
    }

    function refreshSavedRequests() {
        fetch('/api/requests/saved')
            .then(response => response.json())
            .then(data => {
                const container = document.getElementById('savedRequestsList');
                if (!container) return;

                if (!data.success) {
                    container.innerHTML = `<tr><td colspan="4" class="text-center text-danger">加载失败: ${escapeHtml(data.message || '未知错误')}</td></tr>`;
                    return;
                }

                const requests = data.data || [];  // 修改这里，使用data.data而不是data.requests
                if (requests.length === 0) {
                    container.innerHTML = '<tr><td colspan="4" class="text-center text-muted">暂无保存的请求</td></tr>';
                    return;
                }

                let html = '';
                requests.forEach(req => {
                    html += `                    <tr>
                        <td>${escapeHtml(req.method || 'GET')}</td>
                        <td>${escapeHtml(req.url || '')}</td>
                        <td>${req.requestBody ? '有' : '无'}</td>
                        <td>
                            <button class="btn btn-sm btn-outline-primary load-request" data-request='${safeJsonStringifyAndEscape(req)}'>
                                <i class="bi bi-arrow-repeat"></i> 加载
                            </button>
                            <button class="btn btn-sm btn-outline-warning edit-request edit-request-btn" data-request='${safeJsonStringifyAndEscape(req)}'>
                                <i class="bi bi-pencil"></i> 编辑
                            </button>
                            <button class="btn btn-sm btn-outline-danger delete-request" data-id="${escapeHtml(req.requestId)}">
                                <i class="bi bi-trash"></i> 删除
                            </button>
                        </td>
                    </tr>
                `;
                });
                container.innerHTML = html;
            })
            .catch(error => {
                console.error('获取保存的请求失败:', error);
                const container = document.getElementById('savedRequestsList');
                if (container) {
                    container.innerHTML = `<tr><td colspan="4" class="text-center text-danger">加载失败: ${escapeHtml(error.message)}</td></tr>`;
                }
            });
    }

    function loadRequestIntoEditor(request) {
        const reqUrl = document.getElementById('reqUrl');
        const reqMethod = document.getElementById('reqMethod');
        const requestBody = document.getElementById('requestBody');
        const headersContainer = document.getElementById('requestHeaders');

        if (reqUrl) reqUrl.value = request.url || '';
        if (reqMethod) reqMethod.value = request.method || 'GET';
        if (requestBody) requestBody.value = request.requestBody || '';

        // 清除现有的请求头
        if (headersContainer) {
            headersContainer.innerHTML = '';

            // 添加请求头
            if (request.requestHeaders) {
                for (const [name, value] of Object.entries(request.requestHeaders)) {
                    addHeaderRow(escapeHtml(name), escapeHtml(value));
                }
            }

            // 如果没有任何请求头，至少添加一个空的
            if (!request.requestHeaders || Object.keys(request.requestHeaders).length === 0) {
                addHeaderRow();
            }
        }
    }

    function deleteRequest(requestId) {
        if (!confirm('确定要删除这个请求吗？')) {
            return;
        }

        fetch(`/api/requests/delete/${requestId}`, {
            method: 'DELETE'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('请求已删除', 'success');
                    refreshSavedRequests();
                } else {
                    showNotification('删除失败: ' + data.message, 'danger');
                }
            })
            .catch(error => {
                showNotification('删除失败: ' + error.message, 'danger');
            });
    }

    // 流程测试功能
    function addFlowStep() {
        const container = document.getElementById('flowSteps');
        if (!container) return;

        const stepCount = container.children.length + 1;

        const step = document.createElement('div');
        step.className = 'flow-step';
        step.innerHTML = `
            <span class="step-number">${stepCount}</span>
            <h6>步骤 ${stepCount}</h6>
            <div class="row mb-2">
                <div class="col-md-8">
                    <label class="form-label">URL</label>
                    <input type="url" class="form-control" placeholder="https://api.example.com/endpoint">
                </div>
                <div class="col-md-4">
                    <label class="form-label">方法</label>
                    <select class="form-select">
                        <option value="GET">GET</option>
                        <option value="POST">POST</option>
                        <option value="PUT">PUT</option>
                        <option value="DELETE">DELETE</option>
                    </select>
                </div>
            </div>

            <div class="row mb-2">
                <div class="col-md-12">
                    <label class="form-label">请求体</label>
                    <textarea class="form-control" rows="3" placeholder='{"key": "value"}'></textarea>
                </div>
            </div>

            <div class="variable-extraction">
                <h6>变量提取</h6>
                <div class="extraction-rows">
                    <div class="extraction-row">
                        <input type="text" class="form-control" placeholder="变量名">
                        <input type="text" class="form-control" placeholder="JSON路径 (例: $.data.id)">
                        <button class="btn btn-sm btn-danger remove-extraction">
                            <i class="bi bi-trash"></i>
                        </button>
                    </div>
                </div>
                <button class="btn btn-sm btn-outline-primary mt-2 add-extraction">
                    <i class="bi bi-plus"></i> 添加变量提取
                </button>
            </div>

            <button class="btn btn-sm btn-outline-danger remove-step">
                <i class="bi bi-trash"></i> 删除步骤
            </button>
        `;

        container.appendChild(step);
    }

    function addExtractionRow(container) {
        const row = document.createElement('div');
        row.className = 'extraction-row';
        row.innerHTML = `
            <input type="text" class="form-control" placeholder="变量名">
            <input type="text" class="form-control" placeholder="JSON路径 (例: $.data.id)">
            <button class="btn btn-sm btn-danger remove-extraction">
                <i class="bi bi-trash"></i>
            </button>
        `;
        container.appendChild(row);
    }

    function addFlowStepWithData(request, stepNumber, variableExtractions = {}) {
        const container = document.getElementById('flowSteps');
        if (!container) return;

        const step = document.createElement('div');
        step.className = 'flow-step';
        step.innerHTML = `
            <span class="step-number">${stepNumber}</span>
            <h6>步骤 ${stepNumber}</h6>
            <div class="row mb-2">
                <div class="col-md-8">
                    <label class="form-label">URL</label>
                    <input type="url" class="form-control" placeholder="https://api.example.com/endpoint" value="${escapeHtml(request.url || '')}">
                </div>
                <div class="col-md-4">
                    <label class="form-label">方法</label>
                    <select class="form-select">
                        <option value="GET" ${request.method === 'GET' ? 'selected' : ''}>GET</option>
                        <option value="POST" ${request.method === 'POST' ? 'selected' : ''}>POST</option>
                        <option value="PUT" ${request.method === 'PUT' ? 'selected' : ''}>PUT</option>
                        <option value="DELETE" ${request.method === 'DELETE' ? 'selected' : ''}>DELETE</option>
                    </select>
                </div>
            </div>

            <div class="row mb-2">
                <div class="col-md-12">
                    <label class="form-label">请求体</label>
                    <textarea class="form-control" rows="3" placeholder='{"key": "value"}'>${escapeHtml(request.requestBody || '')}</textarea>
                </div>
            </div>

            <div class="variable-extraction">
                <h6>变量提取</h6>
                <div class="extraction-rows">
                    ${Object.keys(variableExtractions).length > 0 ?
            Object.entries(variableExtractions).map(([varName, jsonPath]) => `
                        <div class="extraction-row">
                            <input type="text" class="form-control" placeholder="变量名" value="${escapeHtml(varName)}">
                            <input type="text" class="form-control" placeholder="JSON路径 (例: $.data.id)" value="${escapeHtml(jsonPath)}">
                            <button class="btn btn-sm btn-danger remove-extraction">
                                <i class="bi bi-trash"></i>
                            </button>
                        </div>
                      `).join('') :
            `<div class="extraction-row">
                          <input type="text" class="form-control" placeholder="变量名">
                          <input type="text" class="form-control" placeholder="JSON路径 (例: $.data.id)">
                          <button class="btn btn-sm btn-danger remove-extraction">
                              <i class="bi bi-trash"></i>
                          </button>
                       </div>`
        }
                </div>
                <button class="btn btn-sm btn-outline-primary mt-2 add-extraction">
                    <i class="bi bi-plus"></i> 添加变量提取
                </button>
            </div>

            <button class="btn btn-sm btn-outline-danger remove-step">
                <i class="bi bi-trash"></i> 删除步骤
            </button>
        `;

        container.appendChild(step);
    }

    function renumberFlowSteps() {
        const flowSteps = document.querySelectorAll('.flow-step');
        flowSteps.forEach((step, index) => {
            const stepNumber = index + 1;
            step.querySelector('.step-number').textContent = stepNumber;
            step.querySelector('h6').textContent = `步骤 ${stepNumber}`;
        });
    }

    function executeFlow() {
        const flowName = document.getElementById('flowName');
        if (!flowName || !flowName.value) {
            showNotification('请输入流程名称', 'warning');
            return;
        }

        const steps = [];
        const flowStepElements = document.querySelectorAll('.flow-step');
        flowStepElements.forEach((stepElement, index) => {
            const urlInput = stepElement.querySelector('input[type="url"]');
            const methodSelect = stepElement.querySelector('select');
            const bodyTextarea = stepElement.querySelector('textarea');
            const extractionRows = stepElement.querySelectorAll('.extraction-row');

            if (!urlInput || !urlInput.value) {
                showNotification(`步骤 ${index + 1} 的URL不能为空`, 'warning');
                return;
            }

            // URL格式验证
            try {
                new URL(urlInput.value);
            } catch (e) {
                showNotification(`步骤 ${index + 1} 的URL格式不正确`, 'warning');
                return;
            }

            if (urlInput && urlInput.value) {
                const request = {
                    url: urlInput.value,
                    method: methodSelect ? methodSelect.value : 'GET',
                    requestBody: bodyTextarea ? bodyTextarea.value : undefined
                };

                // 收集变量提取规则
                const variableExtractions = {};
                extractionRows.forEach(row => {
                    const varNameInput = row.querySelector('input:first-child');
                    const jsonPathInput = row.querySelector('input:nth-child(2)');
                    if (varNameInput && jsonPathInput && varNameInput.value && jsonPathInput.value) {
                        variableExtractions[varNameInput.value] = jsonPathInput.value;
                    }
                });

                steps.push({
                    id: `step-${index + 1}`,
                    name: `步骤 ${index + 1}`,
                    request: request,
                    variableExtractions: variableExtractions
                });
            }
        });

        if (steps.length === 0) {
            showNotification('请至少添加一个步骤', 'warning');
            return;
        }

        const flowTest = {
            name: flowName.value,
            steps: steps
        };

        // 显示加载状态
        const executeBtn = document.getElementById('executeFlowBtn');
        const originalHtml = executeBtn.innerHTML;
        executeBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 执行中...';
        executeBtn.disabled = true;

        const resultContainer = document.getElementById('flowExecutionResult');
        if (!resultContainer) {
            // 创建结果容器
            const newResultContainer = document.createElement('div');
            newResultContainer.id = 'flowExecutionResult';
            newResultContainer.className = 'mt-4';
            document.querySelector('#flow .card-body').appendChild(newResultContainer);
        }

        // 显示执行中状态
        document.getElementById('flowExecutionResult').innerHTML = `
            <div class="text-center">
                <div class="spinner-border text-primary" role="status">
                    <span class="visually-hidden">执行中...</span>
                </div>
                <p class="mt-2">正在执行流程，请稍候...</p>
            </div>
        `;

        // 发送执行流程请求
        fetch('/api/requests/flow/execute', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(flowTest)
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('流程执行完成', 'success');
                    displayFlowExecutionResult(data.data);
                } else {
                    showNotification('执行失败: ' + (data.message || '未知错误'), 'danger');
                    document.getElementById('flowExecutionResult').innerHTML =
                        `<div class="alert alert-danger">执行失败: ${escapeHtml(data.message || '未知错误')}</div>`;
                }
            })
            .catch(error => {
                console.error('执行流程时出错:', error);
                showNotification('执行失败: ' + error.message, 'danger');
                document.getElementById('flowExecutionResult').innerHTML =
                    `<div class="alert alert-danger">执行失败: ${escapeHtml(error.message)}</div>`;
            })
            .finally(() => {
                // 恢复按钮状态
                executeBtn.innerHTML = originalHtml;
                executeBtn.disabled = false;
            });
    }

    function displayFlowExecutionResult(results) {
        const resultContainer = document.getElementById('flowExecutionResult');
        if (!resultContainer) return;

        if (!results || results.length === 0) {
            resultContainer.innerHTML = '<div class="alert alert-info">没有执行结果</div>';
            return;
        }

        let html = '<div class="flow-execution-results">';
        results.forEach((result, index) => {
            const statusClass = result.status >= 200 && result.status < 300 ? 'success' : 'danger';
            html += `
                <div class="card mb-2">
                    <div class="card-header">
                        <span class="badge bg-primary">步骤 ${index + 1}</span>
                        <span class="ms-2">${escapeHtml(result.url || '')}</span>
                        <span class="badge bg-${statusClass} float-end">${result.status || 'N/A'}</span>
                    </div>
                    <div class="card-body">
                        ${result.responseBody ? `
                            <h6>响应体</h6>
                            <pre class="bg-light p-2">${escapeHtml(result.responseBody)}</pre>
                        ` : ''}
                        ${result.extractedVariables && Object.keys(result.extractedVariables).length > 0 ? `
                            <h6>提取的变量</h6>
                            <ul>
                                ${Object.entries(result.extractedVariables).map(([name, value]) =>
                `<li><strong>${escapeHtml(name)}:</strong> ${escapeHtml(value)}</li>`
            ).join('')}
                            </ul>
                        ` : ''}
                    </div>
                </div>
            `;
        });
        html += '</div>';

        resultContainer.innerHTML = html;
    }

    function saveFlow() {
        const flowName = document.getElementById('flowName');
        if (!flowName || !flowName.value) {
            showNotification('请输入流程名称', 'warning');
            return;
        }

        const steps = [];
        const flowStepElements = document.querySelectorAll('.flow-step');
        flowStepElements.forEach((stepElement, index) => {
            const urlInput = stepElement.querySelector('input[type="url"]');
            const methodSelect = stepElement.querySelector('select');
            const bodyTextarea = stepElement.querySelector('textarea');
            const extractionRows = stepElement.querySelectorAll('.extraction-row');

            if (!urlInput || !urlInput.value) {
                showNotification(`步骤 ${index + 1} 的URL不能为空`, 'warning');
                return;
            }

            // URL格式验证
            try {
                new URL(urlInput.value);
            } catch (e) {
                showNotification(`步骤 ${index + 1} 的URL格式不正确`, 'warning');
                return;
            }

            if (urlInput && urlInput.value) {
                const request = {
                    url: urlInput.value,
                    method: methodSelect ? methodSelect.value : 'GET',
                    requestBody: bodyTextarea ? bodyTextarea.value : undefined
                };

                // 收集变量提取规则
                const variableExtractions = {};
                extractionRows.forEach(row => {
                    const varNameInput = row.querySelector('input:first-child');
                    const jsonPathInput = row.querySelector('input:nth-child(2)');
                    if (varNameInput && jsonPathInput && varNameInput.value && jsonPathInput.value) {
                        variableExtractions[varNameInput.value] = jsonPathInput.value;
                    }
                });

                steps.push({
                    id: `step-${index + 1}`,
                    name: `步骤 ${index + 1}`,
                    request: request,
                    variableExtractions: variableExtractions
                });
            }
        });

        if (steps.length === 0) {
            showNotification('请至少添加一个步骤', 'warning');
            return;
        }

        const flowTest = {
            name: flowName.value,
            steps: steps
        };

        // 发送保存流程请求
        fetch('/api/requests/flow/save', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(flowTest)
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('流程已保存', 'success');
                    refreshSavedFlows();
                } else {
                    showNotification('保存失败: ' + (data.message || '未知错误'), 'danger');
                }
            })
            .catch(error => {
                console.error('保存流程时出错:', error);
                showNotification('保存失败: ' + error.message, 'danger');
            });
    }

    function refreshSavedFlows() {
        fetch('/api/requests/flow/saved')
            .then(response => response.json())
            .then(data => {
                const container = document.getElementById('savedFlowsList');
                if (!container) return;

                if (!data.success) {
                    container.innerHTML = `<tr><td colspan="4" class="text-center text-danger">加载失败: ${escapeHtml(data.message || '未知错误')}</td></tr>`;
                    return;
                }

                const flows = data.data || [];  // 修改这里，使用data.data而不是data.flows
                if (flows.length === 0) {
                    container.innerHTML = '<tr><td colspan="4" class="text-center text-muted">暂无保存的流程</td></tr>';
                    return;
                }

                let html = '';
                flows.forEach(flow => {
                    html += `                    <tr>
                        <td>${escapeHtml(flow.name)}</td>
                        <td>${flow.steps ? flow.steps.length : 0}</td>
                        <td>-</td>
                        <td>
                            <button class="btn btn-sm btn-outline-primary load-flow" data-flow='${safeJsonStringifyAndEscape(flow)}'>
                                <i class="bi bi-arrow-repeat"></i> 加载
                            </button>
                            <button class="btn btn-sm btn-outline-danger delete-flow" data-id="${escapeHtml(flow.id)}">
                                <i class="bi bi-trash"></i> 删除
                            </button>
                        </td>
                    </tr>
                `;
                });
                container.innerHTML = html;
            })
            .catch(error => {
                console.error('获取保存的流程失败:', error);
                const container = document.getElementById('savedFlowsList');
                if (container) {
                    container.innerHTML = `<tr><td colspan="4" class="text-center text-danger">加载失败: ${escapeHtml(error.message)}</td></tr>`;
                }
            });
    }

    function loadFlowIntoEditor(flow) {
        const flowName = document.getElementById('flowName');
        const stepsContainer = document.getElementById('flowSteps');

        if (flowName) flowName.value = flow.name || '';

        // 清除现有的步骤
        if (stepsContainer) {
            stepsContainer.innerHTML = '';

            // 添加步骤
            if (flow.steps) {
                flow.steps.forEach((step, index) => {
                    addFlowStepWithData(step.request, index + 1, step.variableExtractions || {});
                });
            }

            // 如果没有任何步骤，至少添加一个空的
            if (!flow.steps || flow.steps.length === 0) {
                addFlowStep();
            }
        }
    }

    function deleteFlow(flowId) {
        if (!confirm('确定要删除这个流程吗？')) {
            return;
        }

        fetch(`/api/requests/flow/delete/${flowId}`, {
            method: 'DELETE'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('流程已删除', 'success');
                    refreshSavedFlows();
                } else {
                    showNotification('删除失败: ' + data.message, 'danger');
                }
            })
            .catch(error => {
                showNotification('删除失败: ' + error.message, 'danger');
            });
    }

    function startMonitoring() {
        const monitorUrl = document.getElementById('monitorUrl');
        const interceptToggle = document.getElementById('interceptToggle');
        const interceptPattern = document.getElementById('interceptPattern');
        const startMonitorBtn = document.getElementById('startMonitorBtn');
        const stopMonitorBtn = document.getElementById('stopMonitorBtn');
        const monitorPanel = document.getElementById('monitorPanel');

        if (!monitorUrl || !monitorUrl.value) {
            showNotification('请输入要监控的URL', 'warning');
            return;
        }

        // URL格式验证
        try {
            new URL(monitorUrl.value);
        } catch (e) {
            showNotification('请输入有效的URL', 'warning');
            return;
        }

        // 发送开始监控命令
        if (isConnected && ws) {
            ws.send(JSON.stringify({
                type: 'start',
                url: monitorUrl.value
            }));

            if (interceptToggle && interceptToggle.checked && interceptPattern) {
                ws.send(JSON.stringify({
                    type: 'setInterceptRules',
                    enabled: true,
                    pattern: interceptPattern.value
                }));
            }

            if (startMonitorBtn) startMonitorBtn.disabled = true;
            if (stopMonitorBtn) stopMonitorBtn.disabled = false;

            if (monitorPanel) {
                monitorPanel.innerHTML = '<div class="text-center text-muted">等待请求数据...</div>';
            }
        } else {
            showNotification('WebSocket未连接，无法启动监控', 'danger');
        }
    }

    function stopMonitoring() {
        const startMonitorBtn = document.getElementById('startMonitorBtn');
        const stopMonitorBtn = document.getElementById('stopMonitorBtn');
        const monitorPanel = document.getElementById('monitorPanel');

        if (isConnected && ws) {
            ws.send(JSON.stringify({
                type: 'setInterceptRules',
                enabled: false,
                pattern: ''
            }));

            if (startMonitorBtn) startMonitorBtn.disabled = false;
            if (stopMonitorBtn) stopMonitorBtn.disabled = true;

            if (monitorPanel) {
                monitorPanel.innerHTML = '<div class="text-center text-muted">监控已停止</div>';
            }
        }
    }

    // HTTPS证书相关函数
    function downloadCACertificate() {
        // 创建一个隐藏的下载链接
        const link = document.createElement('a');
        link.href = '/api/certificate/download';
        link.download = 'webcrawler-ca.crt';
        link.style.display = 'none';

        // 添加到页面并触发点击
        document.body.appendChild(link);
        link.click();

        // 清理
        document.body.removeChild(link);

        showNotification('CA证书下载已开始，请按照浏览器提示保存文件', 'info');
    }

    function checkCertificateStatus() {
        const certStatus = document.getElementById('certStatus');
        if (!certStatus) return;

        certStatus.innerHTML = '<div class="text-muted">检查中...</div>';

        fetch('/api/certificate/status')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    certStatus.innerHTML = `
                        <div class="alert alert-success mb-0">
                            <i class="bi bi-check-circle-fill"></i> 证书已生成，可以下载并安装到系统或浏览器中
                        </div>
                    `;
                } else {
                    certStatus.innerHTML = `
                        <div class="alert alert-warning mb-0">
                            <i class="bi bi-exclamation-triangle-fill"></i> ${escapeHtml(data.message || '证书未准备好')}
                        </div>
                    `;
                }
            })
            .catch(error => {
                certStatus.innerHTML = `
                    <div class="alert alert-danger mb-0">
                        <i class="bi bi-x-circle-fill"></i> 检查失败: ${escapeHtml(error.message)}
                    </div>
                `;
            });
    }

    // 工具函数
    function showNotification(message, type = 'info') {
        // 创建通知元素
        const notification = document.createElement('div');
        notification.className = `alert alert-${type} alert-dismissible fade show notification`;
        notification.innerHTML = `
            ${escapeHtml(message)}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        `;

        // 添加到通知容器
        notificationContainer.appendChild(notification);

        // 5秒后自动移除
        setTimeout(() => {
            if (notification.parentNode) {
                notification.parentNode.removeChild(notification);
            }
        }, 5000);
    }

    function escapeHtml(text) {
        if (!text) return '';
        const map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };
        return text.toString().replace(/[&<>"']/g, function(m) { return map[m]; });
    }

    // 调试功能处理函数
    // 调试功能处理函数
    function createDebugSessionHandler() {
        const pageId = document.getElementById('debugPageId').value;
        if (!pageId) {
            showNotification('请输入页面ID', 'warning');
            return;
        }

        fetch('/api/debug/session', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `pageId=${encodeURIComponent(pageId)}`
        })
            .then(response => response.json())
            .then(data => {
                if (data.status === 'success') {
                    currentDebugSessionId = data.sessionId;
                    document.getElementById('debugSessionControls').style.display = 'block';
                    document.getElementById('debugStatus').innerHTML =
                        '<div class="alert alert-success mb-0">调试会话已创建: ' + currentDebugSessionId + '</div>';
                    showNotification('调试会话已创建', 'success');
                    enableDebugControls();
                    refreshBreakpointsList(); // 初始化断点列表

                    // 清空变量信息显示
                    const variablesContainer = document.getElementById('debugVariables');
                    if (variablesContainer) {
                        variablesContainer.textContent = '暂无变量信息';
                    }
                } else {
                    showNotification('创建调试会话失败: ' + (data.error || '未知错误'), 'danger');
                }
            })
            .catch(error => {
                showNotification('创建调试会话失败: ' + error.message, 'danger');
            });
    }

    function setJsBreakpointHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        const url = document.getElementById('jsBreakpointUrl').value;
        const lineNumber = parseInt(document.getElementById('jsBreakpointLine').value);
        const columnNumber = parseInt(document.getElementById('jsBreakpointColumn').value);
        const condition = document.getElementById('jsBreakpointCondition').value;

        if (!url) {
            showNotification('请输入JavaScript脚本URL', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/breakpoints/javascript`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                url: url,
                lineNumber: lineNumber,
                columnNumber: columnNumber,
                condition: condition
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('JavaScript断点设置成功', 'success');
                } else {
                    showNotification('JavaScript断点设置失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('JavaScript断点设置失败: ' + error.message, 'danger');
            });
    }

    function setRequestBreakpointHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        const urlPattern = document.getElementById('requestBreakpointPattern').value;
        if (!urlPattern) {
            showNotification('请输入请求URL模式', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/breakpoints/request`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                urlPattern: urlPattern
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('请求断点设置成功', 'success');
                } else {
                    showNotification('请求断点设置失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('请求断点设置失败: ' + error.message, 'danger');
            });
    }

    function setExceptionBreakpointHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        const type = document.getElementById('exceptionBreakpointType').value;

        fetch(`/api/debug/${currentDebugSessionId}/breakpoints/exception`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                type: type
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('异常断点设置成功', 'success');
                } else {
                    showNotification('异常断点设置失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('异常断点设置失败: ' + error.message, 'danger');
            });
    }

    function resumeDebugHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/resume`, {
            method: 'POST'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('继续执行', 'success');
                } else {
                    showNotification('继续执行失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('继续执行失败: ' + error.message, 'danger');
            });
    }

    function stepOverDebugHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/step-over`, {
            method: 'POST'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('单步跳过', 'success');
                } else {
                    showNotification('单步跳过失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('单步跳过失败: ' + error.message, 'danger');
            });
    }

    function stepIntoDebugHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/step-into`, {
            method: 'POST'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('单步进入', 'success');
                } else {
                    showNotification('单步进入失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('单步进入失败: ' + error.message, 'danger');
            });
    }

    function stepOutDebugHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/step-out`, {
            method: 'POST'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('单步跳出', 'success');
                } else {
                    showNotification('单步跳出失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('单步跳出失败: ' + error.message, 'danger');
            });
    }

    // 处理调试分析按钮点击事件
    function debugAnalysisHandler(e) {
        e.preventDefault();

        const url = document.getElementById('urlInput').value;
        const username = document.getElementById('usernameInput').value;
        const password = document.getElementById('passwordInput').value;

        if (!url) {
            showNotification('请输入目标网址', 'warning');
            return;
        }

        // 验证URL格式
        try {
            new URL(url);
        } catch (e) {
            showNotification('请输入有效的URL', 'warning');
            return;
        }

        // 显示加载状态
        const debugBtn = document.getElementById('debugAnalysisBtn');
        const originalHtml = debugBtn.innerHTML;
        debugBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 调试分析中...';
        debugBtn.disabled = true;

        // 构造请求参数
        const formData = new FormData();
        formData.append('url', url);
        formData.append('headless', 'false'); // 调试模式下使用非无头模式，方便查看
        if (username) formData.append('username', username);
        if (password) formData.append('password', password);

        // 发送调试分析请求
        fetch('/analyze-with-debug', {
            method: 'POST',
            body: formData
        })
            .then(response => response.text())
            .then(html => {
                // 使用新的DOM元素替换当前内容而不是document.write
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = html;
                const newContent = tempDiv.querySelector('body');
                if (newContent) {
                    document.querySelector('body').innerHTML = newContent.innerHTML;
                    // 重新初始化事件监听器
                    setTimeout(initializeApp, 100);
                    // 显示通知
                    showNotification('调试分析完成', 'success');
                }
            })
            .catch(error => {
                console.error('调试分析出错:', error);
                showNotification('调试分析失败: ' + error.message, 'danger');
            })
            .finally(() => {
                // 恢复按钮状态
                if (debugBtn) {
                    debugBtn.innerHTML = originalHtml;
                    debugBtn.disabled = false;
                }
            });
    }

    // 启用调试控制
    function enableDebugControls() {
        const debugControls = document.querySelectorAll('#debugSessionControls button, #debugSessionControls input, #debugSessionControls select');
        debugControls.forEach(element => {
            element.disabled = false;
        });
    }

    // 禁用调试控制
    function disableDebugControls() {
        const debugControls = document.querySelectorAll('#debugSessionControls button, #debugSessionControls input, #debugSessionControls select');
        debugControls.forEach(element => {
            element.disabled = true;
        });
    }
    function setDomBreakpointHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        const nodeId = parseInt(document.getElementById('domBreakpointNodeId').value);
        const type = document.getElementById('domBreakpointType').value;

        if (!nodeId) {
            showNotification('请输入节点ID', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/breakpoints/dom`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                nodeId: nodeId,
                type: type
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('DOM断点设置成功', 'success');
                    refreshBreakpointsList(); // 刷新断点列表
                } else {
                    showNotification('DOM断点设置失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('DOM断点设置失败: ' + error.message, 'danger');
            });
    }

    function stopDebugHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}`, {
            method: 'DELETE'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('调试会话已停止', 'success');
                    currentDebugSessionId = null;
                    document.getElementById('debugSessionControls').style.display = 'none';
                    document.getElementById('debugStatus').innerHTML =
                        '<div class="alert alert-info mb-0">调试会话已停止</div>';
                    disableDebugControls();
                } else {
                    showNotification('停止调试会话失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('停止调试会话失败: ' + error.message, 'danger');
            });
    }

    function refreshVariablesHandler() {
        if (!currentDebugSessionId) {
            showNotification('请先创建调试会话', 'warning');
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/variables`)
            .then(response => response.json())
            .then(data => {
                const variablesContainer = document.getElementById('debugVariables');
                if (variablesContainer) {
                    if (Object.keys(data).length > 0) {
                        variablesContainer.textContent = JSON.stringify(data, null, 2);
                    } else {
                        variablesContainer.textContent = '无变量信息';
                    }
                }
            })
            .catch(error => {
                showNotification('获取变量信息失败: ' + error.message, 'danger');
            });
    }

    function refreshBreakpointsList() {
        if (!currentDebugSessionId) {
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/breakpoints`)
            .then(response => response.json())
            .then(data => {
                const breakpointsList = document.getElementById('breakpointsList');
                if (breakpointsList) {
                    if (data.length > 0) {
                        let html = '';
                        data.forEach(bp => {
                            html += `
                                <tr>
                                    <td>${escapeHtml(bp.type)}</td>
                                    <td>${escapeHtml(bp.target)}</td>
                                    <td>${bp.lineNumber}:${bp.columnNumber}</td>
                                    <td>
                                        <button class="btn btn-sm btn-danger remove-breakpoint-btn"
                                                data-breakpoint-id="${escapeHtml(bp.id)}">
                                            <i class="bi bi-trash"></i> 删除
                                        </button>
                                    </td>
                                </tr>
                            `;
                        });
                        breakpointsList.innerHTML = html;

                        // 为删除按钮添加事件监听器
                        document.querySelectorAll('.remove-breakpoint-btn').forEach(button => {
                            button.addEventListener('click', function() {
                                const breakpointId = this.getAttribute('data-breakpoint-id');
                                removeBreakpoint(breakpointId);
                            });
                        });
                    } else {
                        breakpointsList.innerHTML = '<tr><td colspan="4" class="text-center text-muted">暂无断点</td></tr>';
                    }
                }
            })
            .catch(error => {
                console.error('获取断点列表失败:', error);
                const breakpointsList = document.getElementById('breakpointsList');
                if (breakpointsList) {
                    breakpointsList.innerHTML = '<tr><td colspan="4" class="text-center text-danger">获取断点列表失败</td></tr>';
                }
            });
    }

    function removeBreakpoint(breakpointId) {
        if (!currentDebugSessionId || !breakpointId) {
            return;
        }

        fetch(`/api/debug/${currentDebugSessionId}/breakpoints/${breakpointId}`, {
            method: 'DELETE'
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification('断点已删除', 'success');
                    refreshBreakpointsList(); // 刷新断点列表
                } else {
                    showNotification('删除断点失败', 'danger');
                }
            })
            .catch(error => {
                showNotification('删除断点失败: ' + error.message, 'danger');
            });
    }
</script>
</body>
</html>
